﻿using System.Collections.Generic;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using System.Windows.Shapes;
using System.Windows.Media;
using System.Diagnostics;
using System.Windows.Threading;
using System;
using System.Windows.Media.Animation;

namespace Kindohm.KSynth.AudioCanvas
{
    public class ConnectionManager
    {
        bool moving;
        Canvas canvas;
        Dictionary<ICanvasControl, List<Connection>> connections;
        ICanvasControl movingControl;
        Dictionary<Line, Storyboard> storyboards;


        public ConnectionManager(Canvas canvas)
        {
            this.storyboards = new Dictionary<Line, Storyboard>();
            this.canvas = canvas;
            this.canvas.MouseMove += new MouseEventHandler(canvas_MouseMove);
            this.connections = new Dictionary<ICanvasControl, List<Connection>>();
        }

        void storyboard_Completed(object sender, EventArgs e)
        {
            ((Storyboard)sender).Begin();
        }

        public Line GetLine(ICanvasControl control, ICanvasControl peer)
        {
            if (this.connections.ContainsKey(control))
            {
                List<Connection> items = this.connections[control];
                foreach (Connection item in items)
                {
                    if (item.Peer == peer)
                        return item.Line;
                }

            }
            return null;
        }


        public void RegisterConnection(ICanvasControl element1, ICanvasControl element2)
        {
            this.CheckExists(element1);
            this.CheckExists(element2);

            Line line = new Line();
            line.Stroke = new SolidColorBrush(Colors.White);
            line.StrokeThickness = 2;

            line.X1 = element1.Translation.X;
            line.Y1 = element1.Translation.Y;
            line.X2 = element2.Translation.X;
            line.Y2 = element2.Translation.Y;

            Connection connection1 = new Connection();
            connection1.Line = line;
            connection1.IsHeadEnd = true;
            connection1.Peer = element2;

            Connection connection2 = new Connection();
            connection2.Line = line;
            connection2.IsHeadEnd = false;
            connection2.Peer = element1;

            this.connections[element1].Add(connection1);
            this.connections[element2].Add(connection2);

            Storyboard storyboard = new Storyboard();
            this.storyboards.Add(line, storyboard);
            ColorAnimation animation = new ColorAnimation();
            animation.From = ((SolidColorBrush)line.Stroke).Color;
            animation.To = Colors.Black;
            
            storyboard.Children.Add(animation);
            Storyboard.SetTarget(animation, ((SolidColorBrush)line.Stroke));
            Storyboard.SetTargetProperty(animation, new PropertyPath("Color"));
            storyboard.AutoReverse = true;
            storyboard.Duration = TimeSpan.FromMilliseconds(500);
            storyboard.BeginTime = TimeSpan.FromSeconds(5);
            storyboard.Completed += new EventHandler(storyboard_Completed);
            storyboard.Begin();


            this.canvas.Children.Add(line);

        }

        public void UnregisterConnection(ICanvasControl element1, ICanvasControl element2)
        {
            List<Connection> items = this.connections[element1];
            for (int i = items.Count - 1; i >= 0; i--)
            {
                if (items[i].Peer == element2)
                {
                    this.canvas.Children.Remove(items[i].Line);
                    if (this.storyboards.ContainsKey(items[i].Line))
                    {
                        Storyboard s = this.storyboards[items[i].Line];
                        s.Stop();
                        s.Children.Clear();
                        this.storyboards.Remove(items[i].Line);
                    }
                    items.RemoveAt(i);
                }
            }

            items = this.connections[element2];
            for (int i = items.Count - 1; i >= 0; i--)
            {
                if (items[i].Peer == element1)
                {
                    if (this.storyboards.ContainsKey(items[i].Line))
                    {
                        Storyboard s = this.storyboards[items[i].Line];
                        s.Stop();
                        s.Children.Clear();
                        this.storyboards.Remove(items[i].Line);
                    }
                    this.canvas.Children.Remove(items[i].Line);
                    items.RemoveAt(i);
                }
            }


        }


        void CheckExists(ICanvasControl element)
        {
            if (!this.connections.ContainsKey(element))
            {
                this.connections.Add(element, new List<Connection>());
                element.MouseEnter += new MouseEventHandler(element_MouseEnter);
                element.MouseLeave += new MouseEventHandler(element_MouseLeave);
                element.MouseLeftButtonDown += new MouseButtonEventHandler(element_MouseLeftButtonDown);
                element.MouseLeftButtonUp += new MouseButtonEventHandler(element_MouseLeftButtonUp);
            }

        }


        void canvas_MouseMove(object sender, MouseEventArgs e)
        {
            if (this.moving & this.movingControl != null)
            {
                if (this.connections.ContainsKey(this.movingControl))
                {
                    foreach (Connection connection in this.connections[this.movingControl])
                    {
                        Line line = connection.Line;
                        if (connection.IsHeadEnd)
                        {
                            Debug.WriteLine("IsHeadEnd");
                            line.X1 = this.movingControl.Translation.X;
                            line.Y1 = this.movingControl.Translation.Y;
                        }
                        else
                        {
                            line.X2 = this.movingControl.Translation.X;
                            line.Y2 = this.movingControl.Translation.Y;
                        }
                    }
                }
            }
        }

        void element_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
        {
            this.moving = false;
        }

        void element_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
        {
            if (this.movingControl != null)
                this.moving = true;
        }

        void element_MouseLeave(object sender, MouseEventArgs e)
        {
            if (!this.moving)
                this.movingControl = null;
        }

        void element_MouseEnter(object sender, MouseEventArgs e)
        {
            this.movingControl = (ICanvasControl)sender;
        }

    }
}
